package com.binance.notification.web.redis;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.binance.notification.web.utils.Constants;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class RedisService {

    private volatile boolean locked = false;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    // @Autowired
    // private DistLockManager distLockManager;

    /**
     * 获取锁的状态
     *
     * @return
     */
    public boolean getLockStatus() {
        return locked;
    }


    /**
     * 分布式锁的实现
     *
     * @return
     */
    public boolean setNxWebsocketLock() {
        // IDistLock lock = distLockManager.buildRedDistLock(Constants.NOTIFICATION_WEBSOCKET_LOCK);
        // return lock.tryLock(10, -1, TimeUnit.SECONDS);
        Long expireTime = System.currentTimeMillis() + Constants.REDIS_WX_LOCK_EXPIRE + 1;
        boolean isSuccess =
                redisTemplate.opsForValue().setIfAbsent(Constants.NOTIFICATION_WEBSOCKET_LOCK, expireTime.toString());
        if (isSuccess) { // 设置成功，表示redis中没有键存在
            return locked = true;
        } else { // 设置失败，表示键已经存在，判断键是否已经过期
            String expireTimeStr = redisTemplate.opsForValue().get(Constants.NOTIFICATION_WEBSOCKET_LOCK);
            log.info("system time is " + System.currentTimeMillis() + ", lock's expire time is " + expireTimeStr);
            if (!StringUtils.isEmpty(expireTimeStr)) {
                long oldExpireTime = Long.parseLong(expireTimeStr);
                if (oldExpireTime < System.currentTimeMillis()) { // 键已经过期
                    String oldExpireTimeStr =
                            redisTemplate.opsForValue().getAndSet(Constants.NOTIFICATION_WEBSOCKET_LOCK,
                                    String.valueOf(System.currentTimeMillis() + Constants.REDIS_WX_LOCK_EXPIRE + 1));
                    if (Long.parseLong(oldExpireTimeStr) < System.currentTimeMillis()) { // 其他线程或者进程重写了键的值
                        return locked = true;
                    }
                }
            }
        }
        return false;

    }

    /**
     * 服务器只要正常，就要适时的更新锁的有效期，以保证服务器的对锁的控制
     */
    public void updateWebsocketLockExpireTime() {

        Long expireTime = System.currentTimeMillis() + Constants.REDIS_WX_LOCK_EXPIRE + 1;
        redisTemplate.opsForValue().set(Constants.NOTIFICATION_WEBSOCKET_LOCK, expireTime.toString());
    }

}
